/**
 * Tokenizer.cpp
 *
 * @author Bematech S.A.
 */

#include "bilbao/util/Tokenizer.h"

namespace bilbao
{
	namespace util
	{
		//--------------------------------------------------------------------------------
		// Construtores e destrutor
		//--------------------------------------------------------------------------------
		Tokenizer::Tokenizer()
			: _buffer( "" ), _token( "" ), _delimiter( DEFAULT_DELIMITER )
		{
			_currPos = _buffer.begin();
		}
		//--------------------------------------------------------------------------------
		Tokenizer::Tokenizer( const String& str, const String& delimiter )
			: _buffer( str ), _token( "" ), _delimiter( delimiter )
		{
			_currPos = _buffer.begin();
		}
		//--------------------------------------------------------------------------------
		Tokenizer::~Tokenizer( void )
		{
			// Do nothing
		}
		//--------------------------------------------------------------------------------
		// reset string buffer, delimiter and the currsor position
		//--------------------------------------------------------------------------------
		void Tokenizer::set( const String& str, const String& delimiter )
		{
			this -> _buffer = str;
			this -> _delimiter = delimiter;
			this -> _currPos = _buffer.begin();
		}
		//--------------------------------------------------------------------------------
		void Tokenizer::setString( const String& str )
		{
			this -> _buffer = str;
			this -> _currPos = _buffer.begin();
		}
		//--------------------------------------------------------------------------------
		void Tokenizer::setDelimiter( const String& delimiter )
		{
			this -> _delimiter = delimiter;
			this -> _currPos = _buffer.begin();
		}
		//--------------------------------------------------------------------------------
		// return the next token
		// If cannot find a token anymore, return "".
		//--------------------------------------------------------------------------------
		String Tokenizer::next( void )
		{
			if( _buffer.size() <= 0 )
				return "";           // skip if buffer is empty

			_token.clear();                              // reset token string

			this -> skipDelimiter();                      // skip leading delimiters

			// append each char to token string until it meets delimiter
			while( _currPos != _buffer.end() && !isDelimiter( *_currPos ) )
			{
				_token += *_currPos;
				++_currPos;
			}

			return _token;
		}
		//--------------------------------------------------------------------------------
		// skip ang leading delimiters
		//--------------------------------------------------------------------------------
		void Tokenizer::skipDelimiter( void )
		{
			while( _currPos != _buffer.end() && isDelimiter( *_currPos ) )
				++_currPos;
		}
		//--------------------------------------------------------------------------------
		// return true if the current character is delimiter
		//--------------------------------------------------------------------------------
		bool Tokenizer::isDelimiter( const char& c )
		{
			return ( _delimiter.find( c ) != String::npos);
		}
		//--------------------------------------------------------------------------------
		// split the input string into multiple tokens
		// This function scans tokens from the current cursor position.
		//--------------------------------------------------------------------------------
		Vector< String > Tokenizer::split( void )
		{
			Vector< String > tokens;
			String token;
			while( ( token = this -> next() ) != "" )
			{
				tokens.push_back( token );
			}

			return tokens;
		}
		//--------------------------------------------------------------------------------

	} // namespace util
} // namespace bilbao
